import copy
import os
import re
import sys

import toml
from bs4 import BeautifulSoup, Tag, NavigableString
from mako.template import Template


def read_toml_conf(file):
    """
    read_conf will read configfile for our project
    """
    try:
        print("读取toml文件,%s" % file)
        with open(file, encoding="utf-8") as configfile:
            confstr = configfile.read()
        return toml.loads(confstr)
    except Exception as e:
        print('Conf File not found. Check the path variable and filename: ')
        sys.exit()


def write_toml_conf(conf, file):
    """
    writeconf will write configfile for our project
    """
    try:
        print("写入toml文件,%s,%s" % (file, conf))
        data = toml.dumps(conf)
        with open(file, mode="w", encoding="utf-8") as configfile:
            configfile.write(data)
        return True
    except Exception as e:
        print('Conf File not found. Check the path variable and filename: ')


def render_template(tpl, *args, **data):
    if not tpl:
        return
    if not args and not data:
        return tpl
    print("模板内容,%s, data:%s" % (tpl, data))
    res = Template(tpl).render(*args, **data)
    print("模板渲染结果,%s" % res)
    return res


def remove_temp_files(temp_file_path_list):
    if not temp_file_path_list:
        return
    for temp_file_path in temp_file_path_list:
        if not temp_file_path:
            continue
        if os.path.exists(temp_file_path):
            os.remove(temp_file_path)
            print("删除临时文件 %s" % temp_file_path)


def determine_text_style(style, style_dict):
    if not style_dict:
        return None
    for (k, v) in style_dict.items():
        if k == style:
            return v
    return style_dict.values()[0]


def suitable_secs(sec=None):
    if not sec:
        return 0
    return (int(sec / 0.04) - 1) * 0.04


def match_condition(condition, data):
    if not condition:
        return True
    new_condition = render_template(condition, **data)
    ret = False
    try:
        ret = eval(new_condition)
    except:
        print('match_condition error, %s, %s' % (condition, data))
    return ret


def make_base_dirs(path):
    base_path = os.path.dirname(path)
    if not os.path.exists(base_path):
        os.makedirs(base_path)


def filter_object_none_value(object):
    for k in list(object.keys()):
        v = object.get(k)
        if v is None:
            object.pop(k)
        elif isinstance(v, dict):
            if len(v) == 0:
                object.pop(k)
            else:
                filter_object_none_value(v)
        elif isinstance(v, (str, list)) and len(v) == 0:
            object.pop(k)
    return object


def pre_process_dataInfo(dataInfo={}):
    if not dataInfo.get("name"):
        dataInfo["name"] = "客户"
    for key in ["maxClaimAmount", "claimAmount", "deathClaimAmount"]:
        if dataInfo.get(key):
            dataInfo[key] = '%g' % round(dataInfo[key] / 10000.0, 1)
    for key in ["annuityAmount", "yearPremium", "dayPremium"]:
        if dataInfo.get(key):
            dataInfo[key] = round(dataInfo[key])
    for key in ["insuranceAmount"]:
        if dataInfo.get(key):
            dataInfo[key] = dataInfo[key] / 10000.0
    return dataInfo


def get_suitable_str_parts(text, separators, max_length):
    one_line = re.sub('[\n]', '', text)
    if one_line.startswith('<speak'):
        return get_str_parts_with_ssml(one_line, separators, max_length)
    else:
        return get_str_parts(one_line, separators, max_length)


def get_str_parts(line_str, separators, max_line_num):
    end_index = 0
    str_parts = []
    while end_index + max_line_num < len(line_str):
        start_index = end_index
        end_index = __get_one_part_index(line_str, separators, max_line_num, start_index)
        if end_index > start_index:
            str_parts.append(line_str[start_index:end_index])
    if end_index < len(line_str) - 1:
        str_parts.append(line_str[end_index:])
    return str_parts


def __get_one_part_index(line_str, separators, max_line_num, start_index=0):
    end_index = 0
    current_str = line_str[start_index:]
    for i, letter in enumerate(current_str):
        if letter in separators:
            if i > max_line_num:
                return start_index + i + 1 if end_index == 0 else end_index
            elif i == max_line_num:
                return start_index + i + 1
            else:
                end_index = start_index + i + 1
    return start_index + len(current_str) if end_index == 0 else end_index


def get_str_parts_with_ssml(line_str, separators, max_line_num):
    soup = BeautifulSoup(line_str, features='html.parser')
    base_tag = soup.contents[0]
    base_tag_name = base_tag.name
    base_tag_attrs = base_tag.attrs
    contents = base_tag.contents
    str_parts = []
    is_end = False
    index = 0
    inner_index = 0
    while not is_end:
        (is_end, index, inner_index, tag_list) = __get_one_part_with_ssml(contents, separators, max_line_num, index,
                                                                          inner_index)
        str_parts.append(__wrap_tag_list_with_ssml(tag_list, base_tag_name, base_tag_attrs))
    return str_parts


def __get_one_part_with_ssml(contents, separators, max_line_num, index=0, inner_index=0):
    ret_tag_list = []
    count = 0
    for i, content in enumerate(contents):
        if i < index:
            continue
        elif i == index:
            if isinstance(content, str):
                parts = get_str_parts(content, separators, max_line_num)
                if inner_index < len(parts) - 1:
                    ret_tag_list.append(NavigableString(parts[inner_index]))
                    return False, index, inner_index + 1, ret_tag_list
                elif inner_index == len(parts) - 1:
                    ret_tag_list.append(NavigableString(parts[inner_index]))
                    count += len(parts[inner_index])
        elif isinstance(content, Tag):
            ret_tag_list.append(content)
            count += len(content.text)
            continue
        elif isinstance(content, str):
            if count > 0 and count + len(content) > max_line_num:
                return False, i, 0, ret_tag_list
            parts = get_str_parts(content, separators, max_line_num)
            if len(parts) == 1:
                ret_tag_list.append(NavigableString(parts[0]))
                count += len(parts[0])
            elif len(parts) > 1:
                ret_tag_list.append(NavigableString(parts[0]))
                return False, i, 1, ret_tag_list
    return True, i, 0, ret_tag_list


def __wrap_tag_list_with_ssml(tag_list, base_tag_name, base_tag_attrs):
    tag = Tag(name=base_tag_name, attrs=base_tag_attrs)
    tag.extend(copy.deepcopy(tag_list))
    return str(tag)
